import { defineStore } from 'pinia';
import { UserManager } from 'oidc-client-ts';
import { User, UserManagerSettings } from 'oidc-client-ts';
import { computed, ref } from 'vue';
import { Nullable } from 'element-plus/es/components/cascader-panel/src/node';
import { usePermissStore } from '@/store/permiss';

class UserInfo {
  date: string;
  user: User;
  // token 有效期时间
  expiresIn: number;

  constructor(newUser: User) {
    // 创建一个表示当前时间的 Date 对象（这会自动是用户的本地时间）  
    var now = new Date();
    // 使用 toISOString() 方法将日期转换为 UTC 格式的 ISO 8601 字符串  
    var utcString = now.toISOString();
    this.date = utcString;
    this.user = newUser
    this.expiresIn = newUser.expires_in
  }

  public static fromJson(json: string): Nullable<UserInfo> {
    if (this.isNullOrEmpty(json)) {
      return null;
    }
    return JSON.parse(json) as UserInfo
  }

  private static isNullOrEmpty(str) {
    return str === null || str === undefined || str.trim() === '';
  }

  private static diffInSeconds(date1: Date, date2: Date): number {
    // 确保 date1 在 date2 之前，否则交换它们  
    if (date1 > date2) {
      [date1, date2] = [date2, date1];
    }

    // 获取两个日期的毫秒数  
    let diffInMilliseconds = date2.getTime() - date1.getTime();

    // 将毫秒数转换为秒数  
    let diffInSeconds = Math.floor(diffInMilliseconds / 1000);

    return diffInSeconds;
  }

  public static isValid(userInfo: UserInfo): boolean {
    if (UserInfo.isNullOrEmpty(userInfo.date)) {
      return false
    }

    // 使用new Date()构造函数将字符串转换回Date对象  
    let utcDate = new Date(userInfo.date);
    let now = new Date();
    let seconds: number = UserInfo.diffInSeconds(utcDate, now)

    // 判断时间是否过期
    if (seconds >= userInfo.expiresIn) {
      return false;
    }
    else {
      return true;
    }
  }
}

export const useOidcStore = defineStore('oidc', () => {
  const userManagerSettings: UserManagerSettings = {
    authority: 'https://localhost:44311',
    client_id: 'FlyingEyeWebApp',
    client_secret: '1q2w3e*',
    // 登录重定向 URI
    redirect_uri: 'https://localhost:44388/signin-oidc',
    response_type: 'code',
    // 注销重定向 URI
    post_logout_redirect_uri: 'https://localhost:44388/login',
    // 这两个参数与redirect_uri和post_logout_redirect_uri类似，但它们专门用于使用弹出窗口（popup）的认证和注销流程。
    // 当使用弹出窗口进行授权码流程时，这个参数指定了弹出窗口在成功授权后应被重定向到的URI。
    popup_redirect_uri: 'https://localhost:44388/signout-callback-oidc',
    // 当使用弹出窗口进行注销流程时，这个参数指定了弹出窗口在注销成功后应被重定向到的URI。
    popup_post_logout_redirect_uri: 'https://localhost:44388/login',
  };
  const userManager = new UserManager(userManagerSettings);

  // 当前登录的用户
  const currentUser = ref<Nullable<User>>(null)

  // 是否已经登录
  const isLogin = computed(() => {
    return currentUser.value != null;
  })

  // 用户 token
  const bearerToken = computed<Nullable<string>>(() => {
    if (currentUser.value != null) {
      return currentUser.value.token_type + ' ' + currentUser.value.access_token;
    }
    else {
      return null
    }
  })

  const cookie = ref<Nullable<string>>()

  // 登录重定向
  async function signinRedirectAsync() {
    return await userManager.signinRedirect()
  }

  // 登录重定向回调
  async function signinRedirectCallbackAsync() {
    let user = await userManager.signinRedirectCallback();

    // 登录成功后，缓存用户信息，并设置 app 用户信息
    if (user != null) {
      cacheUserInfo(new UserInfo(user));
      setUserInfo(user);
    }
  }

  function cacheUserInfo(userInfo: UserInfo) {
    localStorage.setItem('userInfo', JSON.stringify(userInfo))
  }

  // 设置用户信息
  function setUserInfo(user: User) {
    cookie.value = document.cookie
    currentUser.value = user;
    let permiss = usePermissStore()
    localStorage.setItem('vuems_name', user.profile.given_name);
    // 设置用户权限
    const keys = permiss.defaultList[user.profile.given_name == 'admin' ? 'admin' : 'user'];
    permiss.handleSet(keys);
  }

  // 注销登录
  function signout() {
    currentUser.value = null;
    cookie.value = ''
    localStorage.removeItem('vuems_name');
    // 注销登录，清除用户缓存
    localStorage.removeItem('userInfo');
  }

  // 重置用户状态
  function trySetUserInfoFromCache() {
    // 如果未登录，才会可能从缓存里加载用户信息
    if (!isLogin.value) {

      const userJson = localStorage.getItem('userInfo')
      let userInfo = UserInfo.fromJson(userJson);

      if (userInfo != null) {
        let isValidUserInfo = UserInfo.isValid(userInfo);

        // 如果存在用户缓存，并且缓存有效，直接用缓存的用户信息设置 app 用户信息
        if (isValidUserInfo) {
          setUserInfo(userInfo.user)
        }
      }
    }
  }

  return { userManager, currentUser, bearerToken, isLogin, signinRedirectAsync, signinRedirectCallbackAsync, signout, trySetUserInfoFromCache };
});
